 //
//  GameLayer.cpp
//  Demo
//
//  Created by CG on 13-10-3.
//
//

#include "GameLayer.h"


GameLayer::GameLayer()
{
    this->init();
}

GameLayer::~GameLayer()
{
    if (m_pWorld)
    {
        delete m_pWorld;
        m_pWorld = NULL;
    }
    
    
}


bool GameLayer::init()
{
    CCLayer::init();
    
    setTouchEnabled(true);
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, kGameLayerTouchPriority, false);

    scheduleUpdate();


    this->CreateLayout();
    this->CreateGround();
    this->CreateBalls();
    this->CreateBucket();
    this->CreateObstacles();
    
    
    
    //////////
    //box2d debug draw
    debugDraw = new GLESDebugDraw(kPTM_RATIO);
    m_pWorld->SetDebugDraw(debugDraw);
    
    uint32 flags = 0;
    flags += b2Draw::e_shapeBit;
    
    //b2Draw::e_centerOfMassBit;   //获取需要显示debugdraw的块
    //b2Draw::e_aabbBit;  //AABB块
    //b2Draw::e_centerOfMassBit; 物体质心
    //b2Draw::e_jointBit;  //关节
    //b2Draw::e_shapeBit;   形状
    
    flags += b2Draw::e_jointBit;
    flags += b2Draw::e_aabbBit;
    flags += b2Draw::e_pairBit;
    flags += b2Draw::e_centerOfMassBit;
    
    debugDraw->SetFlags(flags);
    ///////////
    
    return true;
}



void GameLayer::CreateGround()
{
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();

    b2Vec2 gravity;
    gravity.Set(Box2DGravity.x, Box2DGravity.y);
    m_pWorld = new b2World(gravity);
    m_pWorld->SetAllowSleeping(true);
    m_pWorld->SetContinuousPhysics(true);
    
    //wcg: add collision
    MyContactListener* pContactListener = new MyContactListener();
    m_pWorld->SetContactListener(pContactListener);
    
    //end
    
    b2BodyDef groundBodyDef;
    groundBodyDef.position.Set(0, 0);
    
    b2Body* groundBody = m_pWorld->CreateBody(&groundBodyDef);
    
    b2EdgeShape groundBoxEdge;
    
    //bottom
    groundBoxEdge.Set(b2Vec2(0, 0), b2Vec2(winSize.width / kPTM_RATIO, 0));
    groundBody->CreateFixture(&groundBoxEdge, 0);
    //top
    groundBoxEdge.Set(b2Vec2(0, winSize.height/kPTM_RATIO), b2Vec2(winSize.width/kPTM_RATIO, winSize.height/kPTM_RATIO));
    groundBody->CreateFixture(&groundBoxEdge, 0);
    //left
    groundBoxEdge.Set(b2Vec2(0, winSize.height/kPTM_RATIO), b2Vec2(0, 0));
    groundBody->CreateFixture(&groundBoxEdge, 0);
    //right
    groundBoxEdge.Set(b2Vec2(winSize.width/kPTM_RATIO, winSize.height/kPTM_RATIO), b2Vec2(winSize.width/kPTM_RATIO, 0));
    groundBody->CreateFixture(&groundBoxEdge, 0);
}
void GameLayer::CreateLayout()
{
    CCSprite* bgSprite = CCSprite::create("./maps/level1.png");
    bgSprite->setPosition(CCPointMake(getWinSize().width / 2, getWinSize().height / 2));
    bgSprite->setScaleX(getWinSize().width / bgSprite->boundingBox().size.width);
    bgSprite->setScaleY(getWinSize().height / bgSprite->boundingBox().size.height);
    this->addChild(bgSprite, kBackgroundZOrder, kBackgroundTag);
}
void GameLayer::CreateBalls()
{
    Ball* pRedBall = new Ball();
    pRedBall->initWithFileAndType("./circle_orange.png", ObjectType_Red);
    this->addChild(pRedBall, kBallZOrder, kBallTag);
    pRedBall->SetObjectPosition(CCPointMake(200, 200));
    pRedBall->SetObjectScale(0.2f);
    pRedBall->CreateBody(m_pWorld);

    Ball* pBlueBall = new Ball();
    pBlueBall->initWithFileAndType("./circle_green.png", ObjectType_Blue);
    this->addChild(pBlueBall, kBallZOrder, kBallTag);
    pBlueBall->SetObjectPosition(CCPointMake(150, 140));
    pBlueBall->SetObjectScale(0.2f);
    pBlueBall->CreateBody(m_pWorld);
}
void GameLayer::CreateBucket()
{
    Bucket* pBucket = new Bucket();
    pBucket->initWithFileAndType("./circle_green.png", ObjectType_Blue);
    pBucket->SetObjectPosition(CCPointMake(0, 0));
    pBucket->CreateBody(m_pWorld);
    this->addChild(pBucket, kBucketZOrder, kBucketTag);
}
void GameLayer::CreateObstacles()
{
    Obstacle* pObstacle = new Obstacle();
    pObstacle->CreateBody(m_pWorld);
    pObstacle->SetObjectPosition(CCPointMake(0, 0));
    this->addChild(pObstacle);
}



void GameLayer::update(float dt)
{
    this->updateBox2dWorld(dt);
    this->handleCollision();
    CCLayer::update(dt);
    
    
}
void GameLayer::updateBox2dWorld(float dt)
{
    //It is recommended that a fixed time step is used with Box2D for stability
    //of the simulation, however, we are using a variable time step here.
    //You need to make an informed choice, the following URL is useful
    //http://gafferongames.com/game-physics/fix-your-timestep/
    
    int velocityIterations = 8;
    int positionIterations = 8;//1
    
    // Instruct the world to perform a single step of simulation. It is
    // generally best to keep the time step and iterations fixed.
    m_pWorld->Step(dt, velocityIterations, positionIterations);
    
    //Iterate over the bodies in the physics world
    for (b2Body* b = m_pWorld->GetBodyList(); b; b = b->GetNext())
    {
        if (b->GetUserData() != NULL) {
            //Synchronize the AtlasSprites position and rotation with the corresponding body
            BaseObject* myActor = (BaseObject*)b->GetUserData();
            myActor->SetObjectPosition( CCPointMake( b->GetPosition().x * kPTM_RATIO, b->GetPosition().y * kPTM_RATIO) );
            myActor->SetObjectRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );
        }
    }
}

void GameLayer::handleCollision()
{
}



void GameLayer::draw()
{
    CCLayer::draw();
    
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
    
    kmGLPushMatrix();
    
    m_pWorld->DrawDebugData();
    
    kmGLPopMatrix();
    
    CHECK_GL_ERROR_DEBUG();
}



bool GameLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
    return true;
}
void GameLayer::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
    
}
void GameLayer::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
    
}
void GameLayer::ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
    
}
